package com.tao.system.service.sysUser.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tao.common.creo.domain.LoginUser;
import com.tao.common.creo.domain.Result;
import com.tao.common.creo.enums.ResultCode;
import com.tao.common.creo.enums.UserIdentity;
import com.tao.common.redis.service.RedisService;
import com.tao.common.security.service.TokenService;
import com.tao.system.Utils.BCryptUtils;
import com.tao.system.domain.sysUser.SysUser;
import com.tao.system.domain.sysUser.dot.sysUserSaveDTO;
import com.tao.system.domain.sysUser.vo.LoginUserVO;
import com.tao.system.mapper.sysUser.SysUserMapper;
import com.tao.system.service.sysUser.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
@RefreshScope
public class SysUserServiceImpl implements ISysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private TokenService tokenService;

    @Autowired
    RedisService redisService;

    @Value("${jwt.secret}")
    private String secret;
    @Override
    public Result<String> login(String userAccount, String password) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        SysUser user = sysUserMapper
                .selectOne(queryWrapper.select(SysUser::getUserId, SysUser::getPassword, SysUser::getNickName)
                        .eq(SysUser::getSysAccount, userAccount));
        // 用户不存在
        if(user == null) {
            return Result.fail(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        // 登录成功
        if (BCryptUtils.matchesPassword(password, user.getPassword())) {
            // 生成token, 然后返回
            String token = tokenService
                    .creteToken(user.getUserId(), user.getNickName(), secret, UserIdentity.ADMIN.getValue(), null);
            return Result.success(token);
        }else {
            // 密码不正确
            return Result.fail(ResultCode.FAILED_LOGIN);
        }
    }

    /**
     * 管理员注册
     */
    @Override
    public Result<String> add(sysUserSaveDTO sysUserSaveDTO) {
        try {
            // 从数据库获取相与新注册账号相同的用户名
            List<SysUser> sysUserList = sysUserMapper.selectList(
                    new LambdaQueryWrapper<SysUser>()
                            .eq(SysUser::getSysAccount, sysUserSaveDTO.getUserAccount()));
            // 校验查询结果是否为空, 不为空, 账号已经存在
            if(CollectionUtil.isNotEmpty(sysUserList)) {
                return Result.fail(ResultCode.FAILED_USER_EXISTS);
            }

            // 转换对象
            SysUser sysUser = toSysUser(sysUserSaveDTO);
            // 存储到数据库中
            int insert = sysUserMapper.insert(sysUser);
        }catch (Exception e) {
            log.info("e:" + e);
            return Result.fail(ResultCode.FAILED_PARAMS_VALIDATE);
        }
        return Result.success();
    }

    /**
     * 从 reids 中获取用户信息
     * @param token
     * @return
     */
    @Override
    public Result<LoginUserVO> getUserInfo(String token) {
        // 根据token 获取 redis 中存储的用户信息
        LoginUser loginUser = tokenService.getLoginUser(token, secret);

        if(loginUser == null) {
            Result.fail(ResultCode.SUCCESS);
        }
        //  LoginUser转换成LoginUserVO
        LoginUserVO loginUserVO = new LoginUserVO();
        loginUserVO.setNickName(loginUser.getNiceName());

        return Result.success(loginUserVO);
    }

    /**
     * 退出登录
     * 流程
     * 从token获取userId -> 拼接redis key, 删除redis存储信息
     * @return
     */
    @Override
    public Result<Boolean> logout(String token) {
        boolean result = redisService.deleteObject(tokenService.getRedisKey(token, secret));
        if(!result) {
            return Result.success(false);
        }
        return Result.success();
    }

    /**
     * 将前端的对象进行转换
     * @param sysUserSaveDTO 前端对象
     * @return SysUser 数据库对应的用户
     */
    public SysUser toSysUser(sysUserSaveDTO sysUserSaveDTO) {
        SysUser sysUser = new SysUser();
        sysUser.setSysAccount(sysUserSaveDTO.getUserAccount());
        // 将密文添加到对象中
        sysUser.setPassword(BCryptUtils.encryptPassword(sysUserSaveDTO.getPassword()));
        return sysUser;
    }
}
